package cn.sunline.dreamvalue.service.impl;

import cn.sunline.dreamvalue.constant.CommonResult;
import cn.sunline.dreamvalue.constant.DreamValueType;
import cn.sunline.dreamvalue.constant.ResultStatus;
import cn.sunline.dreamvalue.dao.DreamAcctOpenDao;
import cn.sunline.dreamvalue.dto.DreamAcctOpenDTO;
import cn.sunline.dreamvalue.exception.DreamValueExcption;
import cn.sunline.dreamvalue.service.DreamAcctOpenService;
import cn.sunline.dreamvalue.service.HbaseService;
import cn.sunline.dreamvalue.utils.DreamDateUtil;
import cn.sunline.dreamvalue.utils.DreamValueNoGenerateUtil;
import cn.sunline.dreamvalue.utils.RedisOpsUtil;
import cn.sunline.dreamvalue.utils.SubTableUtil;
import org.apache.commons.lang.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.HashMap;
import java.util.Map;

/**
 * @title: DreamValueGetNumServiceImpl
 * @projectName dream-value
 * @description: 开启梦想旅程
 * @author 82345
 * @date 2020/5/8 17:45
 */
@Service
@Transactional
public class DreamAcctOpenServiceImpl implements DreamAcctOpenService {
    public static final Logger log = LoggerFactory.getLogger(DreamAcctOpenServiceImpl.class);
    @Autowired
    private DreamAcctOpenDao dreamAcctOpenDao;

    @Autowired
    private RedisOpsUtil redisOpsUtil;

    @Autowired
    private SubTableUtil subTableUtil;

    @Autowired
    private HbaseService hbaseService;

    @Autowired
    private DreamValueNoGenerateUtil dreamValueNoGenerateUtil;

    /**
     　* @description: 开启梦想旅程
     　* @param [input]
     　* @return cn.sunline.dreamvalue.constant.CommonResult<java.util.Map<java.lang.String,java.lang.String>>
     　* @author 82345
     　* @date 2020/5/8 17:45
     */
    @Transactional(rollbackFor = Throwable.class)
    @Override
    public CommonResult<Map<String, String>> openDreamTravel(DreamAcctOpenDTO input) throws Exception {
        //返回参数定义
        Map<String,String> result = new HashMap<String,String>();
        //参数校验
        if(StringUtils.isEmpty(input.getCrdtNo()) || StringUtils.isEmpty(input.getCustomerNo())
                || StringUtils.isEmpty(input.getStatus()) || StringUtils.isEmpty(input.getDate())
                || StringUtils.isEmpty(input.getTime())){
            throw new DreamValueExcption(ResultStatus.PARAMETER_REQUIRED_FAILED);
        }
        //校验参数值
        if(input.getStatus().equals(DreamValueType.DREAM_ACCT_STATUS_NOT_OPEN.getCode()) || input.getStatus().equals(DreamValueType.DREAM_ACCT_STATUS_NORMAL.getCode())
        || input.getStatus().equals(DreamValueType.DREAM_ACCT_STATUS_CLOSE.getCode())){
        }else{
            throw new DreamValueExcption(ResultStatus.PARAMETER_VALUE_INCORRECT);
        }
        //日期时间格式校验
        if(!DreamDateUtil.isValidDateTime(input.getDate()+input.getTime())){
            throw new DreamValueExcption(ResultStatus.DATE_FORMAT_ERROR);
        }
        //定义梦想账号
        String dreamnum = null;
        Boolean creatFlg = true;
        //hbase中查询证件号映射关系
        Map<String,String> certNoMap = hbaseService.queryCertNoRel(input.getCrdtNo());
        if(null != certNoMap && !certNoMap.isEmpty()){
            dreamnum = certNoMap.get("bi:a2");
            creatFlg = false;
        }

        //hbase中查询客户号映射关系
        Map<String,String> customerIdMap = hbaseService.queryCustomerIdRel(input.getCustomerNo());
        if(null != customerIdMap && !customerIdMap.isEmpty()){
            dreamnum = customerIdMap.get("bi:a2");
            creatFlg = false;
        }

        String status = DreamValueType.DREAM_ACCT_STATUS_NORMAL.getCode();
        //查询客户梦想值状态
        if(StringUtils.isNotEmpty(dreamnum)){
            Map<String,String> dreamAcctMap = hbaseService.queryDreamAcct(dreamnum);
            if(null != dreamAcctMap && !dreamAcctMap.isEmpty()){
                status = dreamAcctMap.get("bi:a1");
            }
        }
        //增加一步mysql的查询，防止操作hbase时的宕机引起的mysql事务没有提交问题
        if(StringUtils.isNotEmpty(dreamnum)){
            Map<String,String> dreamAcct = dreamAcctOpenDao.selectDreamAcctByDreamValuNo(subTableUtil.getTableSuffix(dreamnum),dreamnum);
            if(null == dreamAcct || dreamAcct.isEmpty()){
                creatFlg = true;
            }
        }
        if(creatFlg){
            //新建梦想账号
            if(StringUtils.isEmpty(dreamnum)){
                dreamnum = dreamValueNoGenerateUtil.generateDreamValueNo(DreamValueType.DREAMVALUE_NO_SOURCE_APP.getCode());
            }
            Integer suffix = subTableUtil.getTableSuffix(dreamnum);
            DreamAcctOpenDTO dreaminfo = new DreamAcctOpenDTO();
            dreaminfo.setDreamAcctNo(dreamnum);
            dreaminfo.setDreamValBal(0);
            dreaminfo.setDreamAcctType(DreamValueType.DEFALUT_TYPE.getCode());
            dreaminfo.setSuffix(suffix);
            dreamAcctOpenDao.setDreamNumber(dreaminfo);
            //初始化梦想账号余额表
            dreamAcctOpenDao.setDreamVal(dreaminfo);
            //初始化hbase梦想账户表
            if(!hbaseService.insertCustDreamAcct(dreamnum,input.getStatus(),input.getDate(),input.getTime())){
                log.error("初始化hbase梦想账户表失败");
                throw new DreamValueExcption(ResultStatus.SYS_INNER_EXCEPTION);
            }
        }
        //写入成功标识
        Boolean customerIdFlg = false;
        Boolean certNoFlg = false;
        try{
            //将映射关系写入hbase中
            if(null == customerIdMap || customerIdMap.isEmpty()){
                customerIdFlg = hbaseService.insertCustomerIdRel(input.getCustomerNo(),input.getCrdtNo(),dreamnum);
            }
            if(null == certNoMap || certNoMap.isEmpty()){
                certNoFlg = hbaseService.insertCertNoRel(input.getCrdtNo(),input.getCustomerNo(),dreamnum);
            }
            //更新操作
            if(!creatFlg && !StringUtils.isEmpty(dreamnum) && !input.getStatus().equals(status)){
                hbaseService.insertCustDreamAcct(dreamnum,input.getStatus(),input.getDate(),input.getTime());
            }
            result.put("dreamValueNo",dreamnum);
            //如果是开通账号，且客户号和证件号映射都有了则返回重复请求
            if(null != certNoMap && null != customerIdMap && !customerIdMap.isEmpty() && !certNoMap.isEmpty() && input.getStatus().equals(status) && !creatFlg){
                throw new DreamValueExcption(ResultStatus.REPEAT_REQUEST);
            }
        }catch (Exception e){
            if(customerIdFlg){
                //手动回滚
                hbaseService.deleteCustomerIdRel(input.getCustomerNo());
            }
            if(certNoFlg){
                hbaseService.deleteCertNoRel(input.getCrdtNo());
            }
            log.error("初始化hbase映射关系失败:{}",e.getMessage());
            throw  e;
        }
        return CommonResult.success(result);
    }
}
